package com.regal.packet;

/**
 * $RCSfile: VCard.java,v $
 * $Revision: 1.3 $
 * $Date: 2007/06/11 20:06:44 $
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.StringUtils;

/**
 * A VCard class for use with the <a href="http://www.jivesoftware.org/smack/"
 * target="_blank">SMACK jabber library</a>.
 * <p>
 * <p/> You should refer to the <a
 * href="http://www.jabber.org/jeps/jep-0054.html" target="_blank">JEP-54
 * documentation</a>.
 * <p>
 * <p/> Please note that this class is incomplete but it does provide the most
 * commonly found information in vCards. Also remember that VCard transfer is
 * not a standard, and the protocol may change or be replaced.
 * <p>
 * <p/> <b>Usage:</b>
 * 
 * <pre>
 *  &lt;p/&gt;
 *  // To save VCard:
 *  &lt;p/&gt;
 *  VCard vCard = new VCard();
 *  vCard.setFirstName(&quot;kir&quot;);
 *  vCard.setLastName(&quot;max&quot;);
 *  vCard.setEmailHome(&quot;foo@fee.bar&quot;);
 *  vCard.setJabberId(&quot;jabber@id.org&quot;);
 *  vCard.setOrganization(&quot;Jetbrains, s.r.o&quot;);
 *  vCard.setNickName(&quot;KIR&quot;);
 *  &lt;p/&gt;
 *  vCard.setField(&quot;TITLE&quot;, &quot;Mr&quot;);
 *  vCard.setAddressFieldHome(&quot;STREET&quot;, &quot;Some street&quot;);
 *  vCard.setAddressFieldWork(&quot;CTRY&quot;, &quot;US&quot;);
 *  vCard.setPhoneWork(&quot;FAX&quot;, &quot;3443233&quot;);
 *  &lt;p/&gt;
 *  vCard.save(connection);
 *  &lt;p/&gt;
 *  // To load VCard:
 *  &lt;p/&gt;
 *  VCard vCard = new VCard();
 *  vCard.load(conn); // load own VCard
 *  vCard.load(conn, &quot;joe@foo.bar&quot;); // load someone's VCard
 * </pre>
 * 
 * @author Kirill Maximov (kir@maxkir.com)
 */
public class VCard extends IQ {

	UserDetail userDetail;

	public VCard(String jid) {

		userDetail = new UserDetail(jid);
	}

	/**
	 * Set generic VCard field.
	 * 
	 * @param field
	 *            value of field. Possible values: NICKNAME, PHOTO, BDAY,
	 *            JABBERID, MAILER, TZ, GEO, TITLE, ROLE, LOGO, NOTE, PRODID,
	 *            REV, SORT-STRING, SOUND, UID, URL, DESC.
	 */

	public String getJabberId() {
		return userDetail.getJid();
	}

	public void setJabberId(String jid) {
		userDetail.setJid(jid);

	}
	
	public String getTitle() {
		return userDetail.getTitle();
	}

	public void setTitle(String title) {
		userDetail.setTitle(title);

	}

	public String getRealName() {
		return userDetail.getRealName();
	}

	public void setRealName(String realName) {
		userDetail.setRealName(realName);
	}

	public String getNickName() {
		return userDetail.getNickName();
	}

	public void setNicktName(String nickName) {
		userDetail.setNickName(nickName);
	}

	public String getSex() {
		return userDetail.getSex();
	}

	public void setSex(String sex) {
		userDetail.setSex(sex);
	}

	public String getPosition() {
		return userDetail.getPosition();
	}

	public void setPosition(String Position) {
		userDetail.setPosition(Position);
	}

	public String getMobile() {
		return userDetail.getMobile();
	}

	public void setMobile(String mobile) {
		userDetail.setMobile(mobile);
	}

	public String getEmail() {
		return userDetail.getEmail();
	}

	public void setEmail(String email) {
		userDetail.setEmail(email);
	}

	public String getCompanyName() {
		return userDetail.getCompanyName();
	}

	public void setCompanyName(String companyName) {
		userDetail.setCompanyName(companyName);
	}

	public String getCompanyid() {
		return userDetail.getCompanyid();
	}

	public void setCompanyid(String companyid) {
		userDetail.setCompanyid(companyid);
	}

	public String getPhoneNo() {
		return userDetail.getPhoneNo();
	}

	public void setPhoneno(String phoneno) {
		userDetail.setPhoneNo(phoneno);
	}

	public String getFax() {
		return userDetail.getFax();
	}

	public void setFax(String fax) {
		userDetail.setPhoneNo(fax);
	}

	public String getAddress() {
		return userDetail.getAddress();
	}

	public void setAddress(String address) {
		userDetail.setAddress(address);
	}

	public String getTrade1() {
		return userDetail.getTrade1();
	}

	public void setTrade1(String trade1) {
		userDetail.setTrade1(trade1);
	}

	public String getTrade2() {
		return userDetail.getTrade2();
	}

	public void setTrade2(String trade2) {
		userDetail.setTrade1(trade2);
	}

	public String getTrade3() {
		return userDetail.getTrade3();
	}

	public void setTrade3(String trade3) {
		userDetail.setTrade1(trade3);
	}

	// /

	/**
	 * Set the avatar for the VCard by specifying the url to the image.
	 * 
	 * @param avatarURL
	 *            the url to the image(png,jpeg,gif,bmp)
	 */
	public void setAvatar(URL avatarURL) {
		byte[] bytes = new byte[0];
		try {
			bytes = getBytes(avatarURL);
		} catch (IOException e) {
			e.printStackTrace();
		}

		setAvatar(bytes);
	}

	/**
	 * Specify the bytes for the avatar to use.
	 * 
	 * @param bytes
	 *            the bytes of the avatar.
	 */
	public void setAvatar(byte[] bytes) {
		if (bytes == null) {
			return;
		}

		userDetail.setAvatar(bytes);
	}

	/**
	 * Set the encoded avatar string. This is used by the provider.
	 * 
	 * @param encodedAvatar
	 *            the encoded avatar string.
	 */
	public void setEncodedImage(String encodedAvatar) {
		// TODO Move VCard and VCardProvider into a vCard package.
		userDetail.setAvatar(encodedAvatar);
	}

	/**
	 * Return the byte representation of the avatar(if one exists), otherwise
	 * returns null if no avatar could be found. <b>Example 1</b>
	 * 
	 * <pre>
	 *  // Load Avatar from VCard
	 *  byte[] avatarBytes = vCard.getAvatar();
	 *  &lt;p/&gt;
	 *  // To create an ImageIcon for Swing applications
	 *  ImageIcon icon = new ImageIcon(avatar);
	 *  &lt;p/&gt;
	 *  // To create just an image object from the bytes
	 *  ByteArrayInputStream bais = new ByteArrayInputStream(avatar);
	 *  try {
	 *    Image image = ImageIO.read(bais);
	 *   }
	 *   catch (IOException e) {
	 *     e.printStackTrace();
	 *  }
	 * </pre>
	 * 
	 * @return byte representation of avatar.
	 */
	public byte[] getAvatar() {
		
		if(userDetail.getAvatar() == null){
			return null;
		}
		
		return StringUtils.decodeBase64(userDetail.getAvatar());
	}

	/**
	 * Common code for getting the bytes of a url.
	 * 
	 * @param url
	 *            the url to read.
	 */
	public static byte[] getBytes(URL url) throws IOException {
		final String path = url.getPath();
		final File file = new File(path);
		if (file.exists()) {
			return getFileBytes(file);
		}

		return null;
	}

	private static byte[] getFileBytes(File file) throws IOException {
		BufferedInputStream bis = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(file));
			int bytes = (int) file.length();
			byte[] buffer = new byte[bytes];
			int readBytes = bis.read(buffer);
			if (readBytes != buffer.length) {
				throw new IOException("Entire file not read");
			}
			return buffer;
		} finally {
			if (bis != null) {
				bis.close();
			}
		}
	}

	/**
	 * Returns the SHA-1 Hash of the Avatar image.
	 * 
	 * @return the SHA-1 Hash of the Avatar image.
	 */
	public String getAvatarHash() {
		byte[] bytes = getAvatar();
		if (bytes == null) {
			return null;
		}

		MessageDigest digest;
		try {
			digest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		}

		digest.update(bytes);
		return StringUtils.encodeHex(digest.digest());
	}

	/**
	 * Save this vCard for the user connected by 'connection'. Connection should
	 * be authenticated and not anonymous.
	 * <p>
	 * <p/> NOTE: the method is asynchronous and does not wait for the returned
	 * value.
	 * 
	 * @param connection
	 *            the XMPPConnection to use.
	 * @throws XMPPException
	 *             thrown if there was an issue setting the VCard in the server.
	 */
	public void save(XMPPConnection connection) throws XMPPException {
		checkAuthenticated(connection, true);
		
		ProviderManager.getInstance().addIQProvider("query",
				"jabber:iq:user_detail", new UserDetail.Provider());

		userDetail.setType(IQ.Type.SET);
		userDetail.setFrom(connection.getUser());
		PacketCollector collector = connection
				.createPacketCollector(new PacketIDFilter(userDetail.getPacketID()));
		connection.sendPacket(userDetail);

		UserDetail response = (UserDetail)collector.nextResult(SmackConfiguration
				.getPacketReplyTimeout());

		// Cancel the collector.
		collector.cancel();
		if (response == null) {
			throw new XMPPException("No response from server on status set.");
		}
		if (response.getError() != null) {
			throw new XMPPException(response.getError());
		}
	}

	/**
	 * Load VCard information for a connected user. Connection should be
	 * authenticated and not anonymous.
	 */
	public void load(XMPPConnection connection) throws XMPPException {

		userDetail.load(connection);

	}

	/**
	 * Load VCard information for a given user. Connection should be
	 * authenticated and not anonymous.
	 */
	public void load(XMPPConnection connection, String user)
			throws XMPPException {
		checkAuthenticated(connection, false);

		userDetail.load(connection, user);
	}

	public String getChildElementXML() {
		return userDetail.getChildElementXML();
	}

	private void checkAuthenticated(XMPPConnection connection,
			boolean checkForAnonymous) {
		if (connection == null) {
			throw new IllegalArgumentException("No connection was provided");
		}
		if (!connection.isAuthenticated()) {
			throw new IllegalArgumentException(
					"Connection is not authenticated");
		}
		if (checkForAnonymous && connection.isAnonymous()) {
			throw new IllegalArgumentException("Connection cannot be anonymous");
		}
	}

	public String toString() {
		return getChildElementXML();
	}

}
